#include "../include/head.h"

int epolladd(int epfd,int fd);
int epolldel(int epfd,int fd);

int getstr(const char *src, int n, char *dest, size_t dest_size);
int checkout_num(const char *buf);
int simplejudge(char* readbuf,int* target);
int submit(int netfd,char* buf,int target,ClientVirtualPathStack* p);

int recv_resolver(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack,int socked_fd);


int main(int argc, char *argv[])
{
    // ARGS_CHECK(argc,3);

    //初始化链表栈
    ClientVirtualPathStack* stack=(ClientVirtualPathStack*)calloc(1,sizeof(ClientVirtualPathStack));
    // ClientVirtualPathStack_init(stack);

    //连接socket
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    addr.sin_port=htons(43210);
    int ret=connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    ERROR_CHECK(ret,-1,"connect");

    //epfd初始化
    int epfd=epoll_create(1);
    epolladd(epfd,STDIN_FILENO);
    epolladd(epfd,sockfd);
    
    //缓冲区
    // char recvbuf[4096]={0};  //接收服务端发来的数据
    char readbuf[4096]={0}; //接收stdin数据

    //客户端是否退出标志
    int is_alive=1; //1活 0死

    struct epoll_event readySet[1024]={0};
    while(is_alive){
        int num=epoll_wait(epfd,readySet,1024,-1);
        for(int i=0;i<num;i++){
            if(readySet[i].data.fd==STDIN_FILENO)
            {
                bzero(readbuf,sizeof(readbuf));
                int submittype=-100;
                ssize_t sret=read(STDIN_FILENO,readbuf,sizeof(readbuf));
                if(sret==0){
                    //客户端退出指令
                    is_alive=0;
                    break;
                }else{
                    //去掉接收到的末尾\n换行符
                    readbuf[strlen(readbuf)-1]='\0';  
                    //判断用户输入指令是否正确 正确封包 错误等待用户重新输入
                    LOG_INFO_MSG(readbuf);
                    if(simplejudge(readbuf,&submittype)==0){
                        submit(sockfd,readbuf,submittype,stack);
                    }
                }
            }else if(readySet[i].data.fd==sockfd){
                //对服务端传入的包进行解析
                ResponsePackage* response=(ResponsePackage*)calloc(1,sizeof(ResponsePackage));
                ssize_t sret=recv(sockfd,&response->type,sizeof(int),MSG_WAITALL);
                if(sret==0){
                    printf("检测到服务端关闭！正在关闭客户端\n");
                    free(response);
                    is_alive=0;
                    break;
                }
                recv(sockfd,&response->vir_path_len,sizeof(int),MSG_WAITALL);
                if(response->vir_path_len !=0)
                {
                    recv(sockfd,response->vir_path_val,response->vir_path_len,MSG_WAITALL);
                }
                recv(sockfd,&response->args_len,sizeof(int),MSG_WAITALL);
                if(response->args_len !=0)
                {
                    recv(sockfd,response->args_val,response->args_len,MSG_WAITALL);
                }
                
                // printf("已接收%d\n",response->type);
                recv_resolver(response, stack, sockfd);
                free(response);
            }
              
        }
    }
    free(stack);
    close(sockfd);
    return 0;
}


int epolladd(int epfd,int fd){
    struct epoll_event event;
    event.events=EPOLLIN;
    event.data.fd=fd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);
    return 0;
}

int epolldel(int epfd,int fd){
    epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
    return 0;
}

// 带安全限制的版本 的字符串截取
int getstr(const char *src, int n, char *dest, size_t dest_size) {
    char *workbuf = strdup(src); // 创建可修改副本
    if(!workbuf) return -1;

    char *token = strtok(workbuf, " ");
    int count = 1;
    int result = -1;

    while(token) {
        if(count == n) {
            strncpy(dest, token, dest_size-1);
            dest[dest_size-1] = '\0';
            result = 0;
            break;
        }
        token = strtok(NULL, " ");
        count++;
    }

    free(workbuf);
    return result;
}

//判断用户输入的参数个数是否合规
int checkout_num(const char *buf){
    char tmp[4096]={0};
    memcpy(tmp,buf,strlen(buf));
    char *p=strtok(tmp," ");
    int real=1;
    while(p!=NULL){
        p=strtok(NULL," ");
        real++;
    }
    --real; //去掉加NULL多加的一次
    return  real;
}

//初步判断用户输入
int simplejudge(char* readbuf,int* target){
    int ret=checkout_num(readbuf);
    if(ret>3){
        printf("用户输入的格式有错误，请重新输入!\n");
        LOG_ERR_MSG("用户输入的格式有错误，请重新输入!\n");
        return -1;
    }
    char buf[1024]={0};
    getstr(readbuf,1,buf,1024);
    //printf("123%s\n",buf);

    if(strcmp(buf,"cd")==0){

        //printf("xxxx:%s %d\n", buf,checkout_num(buf));
        if (checkout_num(readbuf) != 2)
        {
            printf("用户输入的格式有错误，请重新输入!\n");
            LOG_ERR_MSG("cd用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_CD;

    }else if(strcmp(buf,"ls")==0){

        if(checkout_num(readbuf)!=1){
            printf("用户输入的格式有错误，请重新输入!\n");
            LOG_ERR_MSG("ls用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_LS;
    }else if(strcmp(buf,"pwd")==0){

        if(checkout_num(readbuf)!=1){
            printf("用户输入的格式有错误，请重新输入!\n");
            LOG_ERR_MSG("pwd用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_PWD;
    }else if(strcmp(buf,"rmdir")==0){

        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            LOG_ERR_MSG("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_RMDIR;

    }else if(strcmp(buf,"mkdir")==0){

        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            LOG_ERR_MSG("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_MKDIR;

    }else if(strcmp(buf,"remove")==0){

        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_REMOVE;

    }
    else if(strcmp(buf,"gets")==0){

        if(checkout_num(readbuf)!=3){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        char p[1024]={0}; 
        getstr(readbuf,3,p,1024);
        if(opendir(p)==NULL){
            printf("此路径不存在!\n");
            return -1;
        }
        *target=C_OP_GETS;

    }else if(strcmp(buf,"puts")==0){
        if(checkout_num(readbuf)!=3){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        char p[1024]={0};
        getstr(readbuf,2,p,1024);
        printf("puts:%s\n",p);
        if(access(p,F_OK)==-1){
            printf("上传的文件不存在!\n");
            return -1;
        }
        *target=C_OP_PUTS;

    }else{
        printf("用户输入的命令有错误，请重新输入!\n");
        return -1;
    }
    return 0;
}



int submit(int netfd,char* buf,int target,ClientVirtualPathStack* p){ //封装包，上传
    RequestPackage* train=(RequestPackage *)calloc(1,sizeof(RequestPackage));
    char vir_path[1024]={0};
    char tmp[1024]={0};
    char tmpp[1024]={0};
    char tmpbuf[2049]={0};
    switch (target)
    {
    case C_OP_LS:
        train->type=C_OP_LS;
        int ret = send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);
        // printf("发送了%d字节\n",ret);
        ClientVirtualPathStack_print(p,train->vir_path_val);
        train->vir_path_len=strlen(train->vir_path_val);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);
        train->args_len=0;
        send(netfd,&train->args_len,sizeof(train->args_len),MSG_NOSIGNAL);
        // printf("ls命令发送成功\n");
        break;
    case  C_OP_PWD:
        train->type=C_OP_PWD;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);
        ClientVirtualPathStack_print(p,train->vir_path_val);
        train->vir_path_len=strlen(train->vir_path_val);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);
        train->args_len=0;
        send(netfd,&train->args_len,sizeof(train->args_len),MSG_NOSIGNAL);
        // printf("pwd命令发送成功\n");
        break;
    case C_OP_CD:
        // 发T
        train->type=C_OP_CD;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发vir_path
        bzero(vir_path,sizeof(vir_path));
        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("cd命令发送成功\n");
        break;
    case C_OP_RMDIR:
        train->type=C_OP_RMDIR;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发vir_path_len
        bzero(vir_path,sizeof(vir_path));
        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("rmdir命令发送成功\n");
        break;
    case C_OP_MKDIR:
        train->type=C_OP_MKDIR;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发vir_path_len
        bzero(vir_path,sizeof(vir_path));
        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("mkdir命令发送成功\n");
        break;

    case C_OP_REMOVE:
        train->type=C_OP_REMOVE;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发vir_path_len
        bzero(vir_path,sizeof(vir_path));
        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("remove命令发送成功\n");
        break;
    case C_OP_GETS:
        train->type=C_OP_GETS_BEGIN;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发vir_path_len
        bzero(vir_path,sizeof(vir_path));
        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024); 
        bzero(tmpp,sizeof(tmpp));
        getstr(buf,3,tmpp,1024);

        bzero(tmpbuf,sizeof(tmpbuf));
        snprintf(tmpbuf, sizeof(tmpbuf), "%s %s", tmp,tmpp);
         
        train->args_len=strlen(tmpbuf);
        memcpy(train->args_val,tmpbuf,train->args_len);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("gets命令发送成功\n");
        break;
    case C_OP_PUTS:
        train->type=C_OP_PUTS_BEGIN;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        ClientVirtualPathStack_print(p,vir_path);
        train->vir_path_len=strlen(vir_path);
        memcpy(train->vir_path_val,vir_path,train->vir_path_len);
        send(netfd,&train->vir_path_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->vir_path_val,train->vir_path_len,MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024); 
        bzero(tmpp,sizeof(tmpp));
        getstr(buf,3,tmpp,1024);
        bzero(tmpbuf,sizeof(tmpbuf));
        sprintf(tmpbuf, "%s %s", tmp,tmpp);
        // printf("%s 与%s == %s\n",tmp,tmpp,tmpbuf); 
        train->args_len=strlen(tmpbuf);
        memcpy(train->args_val,tmpbuf,train->args_len);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        // printf("puts命令发送成功\n");
        break;
    default:

        break;
    }
    free(train);
    return 0;
}


int recv_resolver(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack,int socked_fd){
    int type=presponse->type;
    // printf("client res type:%d\n", type);
    switch (type)
    {
    case RES_CD:
        client_cd(presponse, pvirtualpathstack);
        break;

    case  RES_LS:
        client_ls(presponse, pvirtualpathstack);
        break;

    case RES_GETS_SUCESS:
         //client_gets(presponse,pvirtualpathstack,socked_fd);
         client_gets_mmap2(presponse,pvirtualpathstack,socked_fd);
         break;

    //case RES_PUTS:
    //     client_puts(presponse,pvirtualpathstack,socked_fd);
    //     break;
    case RES_PUTS_SUCESS:
         //client_puts(presponse, pvirtualpathstack, socked_fd);
         client_puts_mmap(presponse, pvirtualpathstack, socked_fd);
         break;
    

    case RES_RMDIR:
        client_rmdir(presponse,pvirtualpathstack);
        break;
    case RES_MKDIR:
        client_mkdir(presponse,pvirtualpathstack);
        break;
    case RES_REMOVE:
        client_rmfile(presponse,pvirtualpathstack);    
        break;
    case RES_PWD:
        client_pwd(presponse, pvirtualpathstack);
        break;
    case RES_ERR_1: //用户所在虚拟目录打不开，清空客户端栈
        // printf("警告！！ 用户所在虚拟目录打不开!\n");
        while(pvirtualpathstack->size != 0){
            ClientVirtualPathStack_pop(pvirtualpathstack);
        }
        fprintf(stderr, "%s\n", presponse->args_val);
    case RES_ERR_2: //用户操作目标目录打不开，返回错误信息
        //printf("1234!\n");
        fprintf(stdout, "%s\n", presponse->args_val);   
        break;   
    default:
        printf("接收错误\n");
        break;
    }
    return 0;
}




